﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using NCommonLib.Extensions;

namespace NPortableEngine
{
    internal class Scouter : IScouter
    {
        internal Scouter(string url,HttpMethodType methodType,ReqType reqType)
        {
            ReqUrl = url;
            MethodType = methodType;
            ReqType = reqType;
        }

        public string ReqUrl { get; private set; }

        public HttpMethodType MethodType { get; private set; }

        public ReqType ReqType { get; private set; }

        public Dictionary<string,object> Headers { get; private set; }

        public Dictionary<string,object> Paras { get; private set; }

        public Func<Stream,byte[]> DecompressAction { get; set; }

        public NParser Parser { get; private set; }

        public ReqMode Mode { get; private set; }

        public IParameterSetter Header(Dictionary<string,object> headerDic)
        {
            Headers = headerDic;
            return this;
        }

        public IDecompressSetter Params(Dictionary<string,object> paramDic)
        {
            Paras = paramDic;
            return this;
        }

        public IStringParserSetterAndIReqModeSetter Decompress(Func<Stream,byte[]> decompressAction)
        {
            DecompressAction = decompressAction;
            return this;
        }

        public IReqModeSetter Parse(NParser parser)
        {
            Parser = parser;
            return this;
        }

        public IExecutorSetter InMode(ReqMode mode)
        {
            Mode = mode;
            return this;
        }

        public async Task<ScouterBackData> Fly(Type djangoType)
        {
            ScouterBackData scouterBackData = new ScouterBackData();
            
            HttpEngine httpEngine = new HttpEngine();
            WebResponse response = null;
            try
            {
                byte[] byteArr = null;
                response = await httpEngine.Request(ReqUrl, Headers, Paras, MethodType, ReqType).ConfigureAwait(false);

                using (Stream stream = response.GetResponseStream())
                {
                    if (DecompressAction != null && response.Headers.AllKeys.Contains("gzipType") && response.Headers["gzipType"].Equals("1"))
                    {
                        byteArr = DecompressAction.Invoke(stream);
                    }
                    else
                    {
                        byteArr = stream.ToByteArray();
                    }
                }

                if (byteArr == null)
                {
                    scouterBackData.IsSuccess = false;
                    scouterBackData.Msg = "Request byteArray is null !";
                    return scouterBackData;
                }

                scouterBackData.IsSuccess = true;
                scouterBackData.Msg = "Success!";

                string json = Encoding.UTF8.GetString(byteArr, 0, byteArr.Length);
                if (Mode == ReqMode.LIGHT)
                {
                    if (string.IsNullOrEmpty(json))
                    {
                        scouterBackData.IsSuccess = false;
                        scouterBackData.Msg = "Server side return json is null.";
                    }
                    else
                    {
                        scouterBackData.ResponseData = json;
                    }
                }
                else if (Mode == ReqMode.WEIGHT)
                {
                    scouterBackData.ResponseData = djangoType.GetDefault();

                    if (Parser != null)
                    {
                        Parser.Parse(json, scouterBackData);
                    }
                    else
                    {
                        scouterBackData.IsSuccess = false;
                        scouterBackData.Msg = "Becasuse u request in weight mode,so you must set parser and need backdata!";
                    }
                }
                else
                {
                    throw new InvalidOperationException("Hi,boy u must set the request mode!");
                }
            }
            catch (Exception ex)
            {
                scouterBackData.IsSuccess = false;
                scouterBackData.Msg = "HttpEngine Request Error!" + ex.Message.ToString();
            }
            finally
            {
                if (response != null)
                {
                    response.Dispose();
                }
                Headers = null;
                Paras = null;
                DecompressAction = null;
                Parser = null;
            }
            return scouterBackData;
        }
    }
}
